package com.campus.counseling.service.impl;

import com.campus.counseling.model.common.exception.ServiceException;
import com.campus.counseling.entity.Appointment;
import com.campus.counseling.entity.ChatMessage;
import com.campus.counseling.entity.ChatSession;
import com.campus.counseling.model.dto.ChatMessageDTO;
import com.campus.counseling.model.dto.ChatSessionDTO;
import com.campus.counseling.model.mapper.ChatMessageMapper;
import com.campus.counseling.model.mapper.ChatSessionMapper;
import com.campus.counseling.model.mapper.AppointmentMapper;
import com.campus.counseling.service.ChatService;
import com.campus.counseling.service.SysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.campus.counseling.util.SecurityUtils;
import com.campus.counseling.entity.SysUser;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.campus.counseling.entity.Counselor;
import com.campus.counseling.model.mapper.CounselorMapper;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Comparator;

@Service
@RequiredArgsConstructor
public class ChatServiceImpl implements ChatService {

    private final ChatMessageMapper chatMessageMapper;
    private final ChatSessionMapper chatSessionMapper;
    private final AppointmentMapper appointmentMapper;
    private final SysUserService userService;
    private final SimpMessagingTemplate messagingTemplate;
    private final CounselorMapper counselorMapper;
    private static final Logger log = LoggerFactory.getLogger(ChatServiceImpl.class);

    @Override
    @Transactional
    public void saveMessage(ChatMessageDTO messageDTO) {
        // 验证发送者和接收者ID
        if (messageDTO.getSenderId() == null || messageDTO.getReceiverId() == null) {
            throw new ServiceException("发送者或接收者ID不能为空");
        }
        
        // 获取会话信息
        ChatSession session = chatSessionMapper.selectByAppointmentId(messageDTO.getAppointmentId());
        if (session == null) {
            throw new ServiceException("找不到对应的会话信息");
        }
        
        // 如果发送者是学生，接收者应该是咨询师的user_id
        if (messageDTO.getSenderId().equals(session.getStudentId())) {
            // 从会话中获取正确的咨询师ID
            messageDTO.setReceiverId(session.getCounselorId());
            log.info("学生发送消息，设置接收者为咨询师ID: {}", session.getCounselorId());
        }
        // 如果发送者是咨询师，接收者应该是学生id
        else if (messageDTO.getSenderId().equals(session.getCounselorId())) {
            messageDTO.setReceiverId(session.getStudentId());
            log.info("咨询师发送消息，设置接收者为学生ID: {}", session.getStudentId());
        }
        
        log.info("修正后的消息接收者ID: {}", messageDTO.getReceiverId());
        
        ChatMessage message = new ChatMessage();
        BeanUtils.copyProperties(messageDTO, message);
        
        // 设置必要的字段
        LocalDateTime now = LocalDateTime.now();
        message.setCreateTime(now);
        message.setUpdateTime(now);
        message.setDeleted(0);
        message.setStatus("SENDING");  // 初始状态为发送中
        
        // 保存消息并获取生成的ID
        chatMessageMapper.insert(message);
        Long generatedId = message.getId();
        
        if (generatedId == null || generatedId == 0) {
            throw new ServiceException("消息ID生成失败");
        }
        
        // 设置生成的ID回DTO
        messageDTO.setId(generatedId);
        log.info("消息保存成功，生成的ID: {}", generatedId);
        
        // 更新会话的最后一条消息
        if (session != null) {
            session.setLastMessageId(generatedId);
            chatSessionMapper.updateById(session);
        }
        
        // 发送确认消息
        try {
            // 更新消息状态为已送达
            message.setStatus("DELIVERED");
            message.setUpdateTime(LocalDateTime.now());
            chatMessageMapper.updateById(message);
            
            // 发送确认通知
            // 发送完整的确认消息
            ChatMessageDTO ack = new ChatMessageDTO();
            ack.setId(generatedId);  // 使用生成的ID
            ack.setStatus("DELIVERED");
            ack.setAppointmentId(message.getAppointmentId());
            ack.setContent(message.getContent());
            ack.setSenderId(message.getSenderId());
            ack.setReceiverId(message.getReceiverId());
            ack.setTime(LocalDateTime.now().toString());
            
            messagingTemplate.convertAndSendToUser(
                message.getSenderId().toString(),
                "/queue/ack",      // 使用专门的确认消息队列
                ack
            );
        } catch (Exception e) {
            log.error("发送确认消息失败", e);
            // 确认消息发送失败不影响主流程
        }
    }

    @Override
    public List<ChatMessageDTO> getChatHistory(Long appointmentId) {
        log.info("获取会话 {} 的历史记录", appointmentId);
        
        // 从数据库获取历史消息
        List<ChatMessage> messages = chatMessageMapper.selectByAppointmentId(appointmentId);
        
        // 转换为 DTO
        return messages.stream()
            .map(msg -> {
                ChatMessageDTO dto = new ChatMessageDTO();
                BeanUtils.copyProperties(msg, dto);
                
                // 设置发送者和接收者信息
                SysUser sender = userService.getById(msg.getSenderId());
                SysUser receiver = userService.getById(msg.getReceiverId());
                
                // 设置名称和头像
                if (sender != null) {
                    dto.setSenderName(sender.getRealName());
                    dto.setSenderAvatar(sender.getAvatar());  // 添加发送者头像
                }
                if (receiver != null) {
                    dto.setReceiverName(receiver.getRealName());
                    dto.setReceiverAvatar(receiver.getAvatar());  // 添加接收者头像
                }
                
                // 使用 createTime 作为消息时间
                dto.setTime(msg.getCreateTime().toString());
                
                return dto;
            })
            .sorted(Comparator.comparing(ChatMessageDTO::getTime))
            .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void markAsRead(Long userId, Long appointmentId) {
        chatMessageMapper.updateStatusToRead(userId, appointmentId);
    }

    @Override
    @Transactional
    public ChatSession getOrCreateSession(Long appointmentId) {
        log.info("开始创建或获取会话, appointmentId: {}", appointmentId);
        
        // 先查找是否存在会话
        ChatSession session = chatSessionMapper.selectOne(
            new LambdaQueryWrapper<ChatSession>()
                .eq(ChatSession::getAppointmentId, appointmentId)
                .eq(ChatSession::getDeleted, 0)
        );
        
        if (session != null) {
            return session;
        }
        
        // 获取预约信息
        Appointment appointment = appointmentMapper.selectById(appointmentId);
        if (appointment == null) {
            throw new ServiceException("预约不存在");
        }
        
        log.info("为预约创建新会话: {}", appointment);
        
        // 获取咨询师信息 - 修改查询条件
        Counselor counselor = counselorMapper.selectOne(
            new LambdaQueryWrapper<Counselor>()
                .eq(Counselor::getId, appointment.getCounselorId())  // 使用 counselor_id
        );
        
        if (counselor == null) {
            throw new ServiceException("咨询师信息不存在");
        }
        
        // 创建新会话
        LocalDateTime now = LocalDateTime.now();
        ChatSession newSession = new ChatSession();
        newSession.setAppointmentId(appointmentId);
        newSession.setStudentId(appointment.getStudentId());
        newSession.setCounselorId(counselor.getUserId());
        newSession.setStatus("ACTIVE");
        newSession.setStartTime(appointment.getAppointmentTime());
        newSession.setEndTime(appointment.getAppointmentTime().plusHours(1));
        newSession.setStudentUnread(0);
        newSession.setCounselorUnread(0);
        newSession.setCreateTime(now);   // 设置创建时间
        newSession.setUpdateTime(now);   // 设置更新时间
        newSession.setDeleted(0);        // 设置删除标记
        
        log.info("当前学生ID: {}, 咨询师ID: {}", newSession.getStudentId(), newSession.getCounselorId());
        
        chatSessionMapper.insert(newSession);
        return newSession;
    }

    @Override
    public List<ChatSessionDTO> getActiveSessions(Long userId) {
        String userRole = SecurityUtils.getUserRole();
        log.info("查询用户 {} (角色: {}) 的活跃会话列表", userId, userRole);
        
        List<ChatSessionDTO> sessions;
        if ("counselor".equals(userRole)) {
            sessions = chatSessionMapper.selectActiveSessionsByCounselorId(userId);
        } else {
            sessions = chatSessionMapper.selectActiveSessionsByStudentId(userId);
        }
        
        // 填充用户头像信息
        for (ChatSessionDTO session : sessions) {
            SysUser student = userService.getById(session.getStudentId());
            SysUser counselor = userService.getById(session.getCounselorId());
            
            if (student != null) {
                session.setStudentAvatar(student.getAvatar());
            }
            if (counselor != null) {
                session.setCounselorAvatar(counselor.getAvatar());
            }
        }
        
        return sessions;
    }

    @Override
    @Transactional
    public void endSession(Long appointmentId) {
        log.info("结束会话: appointmentId={}", appointmentId);
        
        // 获取会话信息
        ChatSession session = chatSessionMapper.selectByAppointmentId(appointmentId);
        if (session == null) {
            throw new ServiceException("会话不存在");
        }
        
        // 检查会话状态
        if ("CLOSED".equals(session.getStatus())) {
            throw new ServiceException("会话已经结束");
        }
        
        // 更新会话状态
        session.setStatus("CLOSED");
        session.setEndTime(LocalDateTime.now());
        boolean updated = chatSessionMapper.updateById(session) > 0;
        
        if (!updated) {
            throw new ServiceException("结束会话失败");
        }
        
        log.info("会话已结束: appointmentId={}", appointmentId);
        
        // 发送会话结束通知给双方
        ChatMessageDTO endMessage = new ChatMessageDTO();
        endMessage.setType("system");
        endMessage.setContent("会话已结束");
        endMessage.setAppointmentId(appointmentId);
        endMessage.setTime(LocalDateTime.now().toString());
        endMessage.setStatus("CLOSED");
        
        // 使用广播消息，只发送一次
        messagingTemplate.convertAndSend(
            "/topic/session/" + appointmentId + "/status",
            endMessage
        );
    }

    @Override
    @Transactional
    public void recallMessage(Long messageId, Long userId) {
        log.info("尝试撤回消息: messageId={}, userId={}", messageId, userId);
        
        // 1. 获取消息并进行基础验证
        ChatMessage message = chatMessageMapper.selectById(messageId);
        validateMessageForRecall(message, userId);
        
        try {
            // 2. 更新消息状态
            message.setStatus("RECALLED");
            message.setContent("此消息已撤回");
            message.setUpdateTime(LocalDateTime.now());
            chatMessageMapper.updateById(message);
            
            // 3. 如果是会话的最后一条消息，更新会话的最后消息显示
            updateSessionLastMessage(message);
            
            // 4. 发送WebSocket通知
            sendRecallNotification(message);
            
            log.info("消息撤回成功: messageId={}", messageId);
        } catch (Exception e) {
            log.error("消息撤回失败", e);
            throw new ServiceException("撤回失败，请重试");
        }
    }

    private void validateMessageForRecall(ChatMessage message, Long userId) {
        if (message == null) {
            throw new ServiceException("消息不存在");
        }
        
        if (!message.getSenderId().equals(userId)) {
            throw new ServiceException("只能撤回自己发送的消息");
        }
        
        // 只能撤回已送达的消息
        if (!"DELIVERED".equals(message.getStatus())) {
            throw new ServiceException("消息尚未送达，无法撤回");
        }
        
        if (LocalDateTime.now().minusMinutes(2).isAfter(message.getCreateTime())) {
            throw new ServiceException("只能撤回2分钟内的消息");
        }
    }

    private void updateSessionLastMessage(ChatMessage message) {
        ChatSession session = chatSessionMapper.selectByAppointmentId(message.getAppointmentId());
        if (session != null && session.getLastMessageId().equals(message.getId())) {
            session.setLastMessageId(message.getId());
            chatSessionMapper.updateById(session);
        }
    }

    private void sendRecallNotification(ChatMessage message) {
        ChatMessageDTO notification = new ChatMessageDTO();
        notification.setId(message.getId());
        notification.setType("system");
        notification.setContent("消息已被撤回");
        notification.setAppointmentId(message.getAppointmentId());
        notification.setStatus("RECALLED");
        notification.setTime(LocalDateTime.now().toString());
        
        messagingTemplate.convertAndSendToUser(
            message.getReceiverId().toString(),
            "/queue/messages",
            notification
        );
    }

}